package org.jeecg.tender.taskJob.b2b10086.historical;

import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.attachment.service.ISysAttachmentService;
import org.jeecg.common.MessageSNUtil;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.FileUtil;
import org.jeecg.common.util.HttpClientUtil;
import org.jeecg.tender.config.WebDriverConfig;
import org.jeecg.tender.constant.PublishTypeEnum;
import org.jeecg.tender.information.entity.TenderInformation;
import org.jeecg.tender.information.service.ITenderInformationService;
import org.jeecg.tender.keyword.entity.TenderSecurityKeywordManagement;
import org.jeecg.tender.keyword.service.ITenderSecurityKeywordManagementService;
import org.jeecg.tender.project.dto.req.SendProjectNoticeReqDto;
import org.jeecg.tender.project.service.ITenderProjectNoticeService;
import org.jeecg.tender.taskJob.b2b10086.support.B2b10086Page;
import org.jeecg.tender.taskJob.b2b10086.support.B2b10086PublishPageReq;
import org.jeecg.tender.taskJob.b2b10086.support.B2b10086Resp;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 安全产品严选测评管理平台:关键字历史数据采集（直接采购公告）补跑
 */
@Slf4j
@Component
public class HistoricalDataB2b10086OneSrouceTaskJob implements Job {

    @Resource
    private WebDriverConfig webDriverConfig;
    @Resource
    private ISysAttachmentService sysAttachmentService;
    @Resource
    private ITenderInformationService tenderInformationService;
    @Resource
    private ITenderSecurityKeywordManagementService tenderSecurityKeywordManagementService;
    @Resource
    private ITenderProjectNoticeService tenderProjectNoticeService;

    /**
     * <a href="https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json">google浏览器驱动下载地址</a>
     **/
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        WebDriver driver = null;
        List<SendProjectNoticeReqDto> noticeInfoList = new ArrayList<>();
        try {
            driver = webDriverConfig.driver();
            Map<Long, String> lableMap = tenderSecurityKeywordManagementService.lambdaQuery().eq(TenderSecurityKeywordManagement::getSubProject,"1907042004999618563")
                    .list()
                    .stream().collect(Collectors.toMap(TenderSecurityKeywordManagement::getId, TenderSecurityKeywordManagement::getKeywordName));

            List<B2b10086PublishPageReq> list = null;

            int current = 0;
            do {
                current++;
                String url = "https://b2b.10086.cn/api-b2b/api-sync-es/white_list_api/b2b/publish/queryList";
                Map<String, Object> params = new HashMap<>(4);
                params.put("companyType", "");
                params.put("current", current);
                params.put("size", 50);
                params.put("name", "");
                //直接采购公告
                params.put("publishOneType", "ONE_SOURCE_PROCUREMENT");
                params.put("publishType", "PROCUREMENT");
                params.put("sfactApplColumn5", "PC");
                // 设置扫描时间范围
                params.put("creationDateStart", DateUtils.formatDate(DateUtils.calculate(new Date(), -180, Calendar.DAY_OF_MONTH), DateUtils.DATE_PATTERN));
                params.put("creationDateEnd", DateUtils.formatDate(new Date(), DateUtils.DATE_PATTERN));

                TypeReference<B2b10086Resp<B2b10086Page<B2b10086PublishPageReq>>> type = new TypeReference<B2b10086Resp<B2b10086Page<B2b10086PublishPageReq>>>(){};
                B2b10086Resp<B2b10086Page<B2b10086PublishPageReq>> resp = HttpClientUtil.postJson(url, params, type);
                if (resp.getCode() == 0) {
                    list = resp.getData().getContent();
                    // 只保存标题
                    for (B2b10086PublishPageReq req : list) {
                        long count = tenderInformationService.lambdaQuery().eq(TenderInformation::getTenderTitle, req.getName()).count();
                        if (count > 0) {
                            log.info("{}已经抓取", req.getName());
                            continue;
                        }
                        List<Long> lableList = lableMap.entrySet().stream()
                                .filter(entry -> req.getName().contains(entry.getValue())).map(Map.Entry::getKey)
                                .collect(Collectors.toList());
                        if (ObjectUtils.isEmpty(lableList)) {
                            log.debug("{}没有安全标签", req.getName());
                            continue;
                        }
                        // 优先直接调用接口获取招标文书明细
                        if (loadDetail(req, noticeInfoList, lableList)) {
                            continue;
                        }

                        String detailUrl = "https://b2b.10086.cn/#/noticeDetail?publishId=%s&publishUuid=%s&publishType=%s&publishOneType=%s";
                        detailUrl = String.format(detailUrl, req.getId(), req.getUuid(), req.getPublishType(), req.getPublishOneType());
                        driver.get(detailUrl);
                        driver.navigate().refresh();
                        try {
                            // 等待页面加载完成
                            List<WebElement> elements = new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("#pdfViewer canvas")));

                            // 获取招标文书
                            JavascriptExecutor executor = (JavascriptExecutor) driver;
                            List<Long> detailList = new ArrayList<>();
                            int fileIdx = 0;
                            for (WebElement canvas: elements) {
                                String imageStr = FileUtil.getFileBase64(String.valueOf(executor.executeScript("return arguments[0].toDataURL('image/png');", canvas)));
                                Long fileId = uploadImage(String.format("%s_%d", req.getName(), fileIdx++), imageStr);
                                if (null != fileId) {
                                    detailList.add(fileId);
                                }
                            }
                            tenderInformationService.saveB2b10086("中国移动采购与招标网", StringUtils.join(detailList, SymbolConstant.COMMA), "image", lableList, req, noticeInfoList, detailUrl, PublishTypeEnum.ONE_SOURCE_PROCUREMENT.getCode());
                        } catch (Exception e) {
                            log.warn("{}获取招标文书失败, 错误原因: ",  detailUrl, e);
                        }
                    }
                }
            } while (ObjectUtils.isNotEmpty(list));



        } catch (Exception e) {
            log.warn("获取招标文书失败, 错误原因: ",  e);
        } finally {
            // 发送通知
//            tenderProjectNoticeService.sendTenderProjectNotice(noticeInfoList);
            // 需要正确关闭驱动; 否则会导致电脑开启进程过多而卡死
            if (driver != null) {
                driver.quit();
            }
            HttpClientUtil.close();
            log.info("移动采购平台爬取任务结束");
        }
    }

    public boolean loadDetail(B2b10086PublishPageReq req, List<SendProjectNoticeReqDto> noticeInfoList, List<Long> lableList) {
        String url = "https://b2b.10086.cn/api-b2b/api-sync-es/white_list_api/b2b/publish/queryDetail";
        Map<String, String> params = new HashMap<>();
        params.put("publishId", req.getId());
        params.put("publishUuid", req.getUuid());
        params.put("publishType", req.getPublishType());
        params.put("sfactApplColumn5", "PC");

        TypeReference<B2b10086Resp<Map<String, Object>>> typeReference = new TypeReference<B2b10086Resp<Map<String, Object>>>() { };
        B2b10086Resp<Map<String, Object>> resp = HttpClientUtil.postJson(url, params, typeReference);
        if (resp.getCode() == 0) {
            String str = resp.getData().get("noticeContent").toString();
            if (!str.startsWith("<")) {
                // 不是html格式，需要通过selenium获取
                return false;
            }
            tenderInformationService.saveB2b10086("中国移动采购与招标网", str, "html", lableList, req, noticeInfoList,url, PublishTypeEnum.ONE_SOURCE_PROCUREMENT.getCode());
            return true;
        }
        return false;
    }

    private Long uploadImage(String name, String base64Image) {
        // 将base64转换为图片文件，并写入到系统临时目录
        String safeFileName = name.replaceAll("[^\\x00-\\x7F]", "_");  // 替换所有非ASCII字符为下划线
        String path = String.format("%sb2b10086/%s.png", System.getProperty("java.io.tmpdir"), safeFileName);  // 使用安全的文件名
        File imageFile = null;
        try {
            imageFile = FileUtil.writeImage(base64Image, path);
            Result<Long> result = sysAttachmentService.uploadFile(imageFile, "system", MessageSNUtil.generateFileMessageSN());
            if (result.isSuccess()) {
                return result.getResult();
            }
            return null;
        } catch (Exception e) {
            log.warn("上传图片失败", e);
           return null;
        } finally {
            if (null != imageFile) {
                imageFile.delete();
            }
        }
    }



}
